{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ce637185-bda7-44bb-aa79-b6a5b21ec851",
   "metadata": {},
   "source": [
    "# 安全聚合\n",
    "\n",
    "安全聚合（secure aggregation）可以表述为：多个参与方各自拥有数据，在不泄露各自私有数据的前提下，合作完成聚合值（比如求和）的计算。\n",
    "\n",
    "安全聚合是联邦学习中的一项重要概念，学术界已经有较多研究，隐语已经在水平联邦梯度/权重聚合、数据统计（比如数据探查、预处理）中使用了安全聚合。\n",
    "\n",
    "下面将开始介绍隐语使用的安全聚合方案。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d52a334d-96c8-4801-b5c1-b12710d469ab",
   "metadata": {},
   "source": [
    "## 准备\n",
    "\n",
    "初始化隐语"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "dff940f3-f88c-4e6e-86f5-0bd00f15e14c",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "E0308 17:16:17.239683816   26319 fork_posix.cc:70]           Fork support is only compatible with the epoll1 and poll polling strategies\n",
      "E0308 17:16:17.251297248   26319 fork_posix.cc:70]           Fork support is only compatible with the epoll1 and poll polling strategies\n",
      "E0308 17:16:17.260081403   26319 fork_posix.cc:70]           Fork support is only compatible with the epoll1 and poll polling strategies\n"
     ]
    }
   ],
   "source": [
    "import secretflow as sf\n",
    "\n",
    "sf.init(['alice', 'bob'], num_cpus=8, log_to_driver=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6fd12c4f-c07c-4218-80ee-b6757482ea40",
   "metadata": {},
   "source": [
    "准备一些待测试数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0bf50097-f1dd-48e9-86f3-3d353ffa2d47",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "arr0:\n",
      " [[0.64818372 0.33600055 0.43811926]\n",
      " [0.7835069  0.25554061 0.71970086]] \n",
      "arr1:\n",
      " [[0.11274985 0.99172087 0.56520836]\n",
      " [0.48992353 0.22364359 0.40473672]]\n",
      "Sum:\n",
      " [[0.76093357 1.32772142 1.00332762]\n",
      " [1.27343043 0.47918421 1.12443758]]\n",
      "Average:\n",
      " [[0.38046678 0.66386071 0.50166381]\n",
      " [0.63671522 0.2395921  0.56221879]]\n",
      "Min:\n",
      " [[0.11274985 0.33600055 0.43811926]\n",
      " [0.48992353 0.22364359 0.40473672]]\n",
      "Max:\n",
      " [[0.64818372 0.99172087 0.56520836]\n",
      " [0.7835069  0.25554061 0.71970086]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "arr0, arr1 = np.random.rand(2, 3), np.random.rand(2, 3)\n",
    "print('arr0:\\n', arr0, '\\narr1:\\n', arr1)\n",
    "\n",
    "print('Sum:\\n', np.sum([arr0, arr1], axis=0))\n",
    "print('Average:\\n', np.average([arr0, arr1], axis=0))\n",
    "print('Min:\\n', np.min([arr0, arr1], axis=0))\n",
    "print('Max:\\n', np.max([arr0, arr1], axis=0))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3759e41-7ee6-4225-a504-969990b73338",
   "metadata": {},
   "source": [
    "构建参与方用于后续的演示。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e7d060f4-a20a-404e-821b-e93e45b8ced3",
   "metadata": {},
   "outputs": [],
   "source": [
    "alice, bob = sf.PYU('alice'), sf.PYU('bob')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a23a3bf-3003-4c7a-a1e9-3bca5fba2679",
   "metadata": {},
   "source": [
    "## 聚合操作\n",
    "\n",
    "隐语提供了多种```Aggregator```供用户选择，每种```Aggregator```都提供了求和(sum)/求平均(average)的功能。\n",
    "\n",
    "### 基于PPU的安全聚合\n",
    "\n",
    "[PPU](../development/ppu.md)是隐语中的一种安全设备，其底层原理为[MPC](https://en.wikipedia.org/wiki/Secure_multi-party_computation)。隐语实现了基于PPU的安全聚合，下面将展示如何使用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "5209d8db-547a-4a2f-a02d-85515554241c",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PPURuntime pid=26652)\u001b[0m I0308 17:16:27.179066 26652 external/com_github_brpc_brpc/src/brpc/server.cpp:1046] Server[ppu::link::internal::ReceiverServiceImpl] is serving on port=33991.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26652)\u001b[0m I0308 17:16:27.179144 26652 external/com_github_brpc_brpc/src/brpc/server.cpp:1049] Check out http://sgx-stable:33991 in web browser.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m I0308 17:16:27.105597 26657 external/com_github_brpc_brpc/src/brpc/server.cpp:1046] Server[ppu::link::internal::ReceiverServiceImpl] is serving on port=49969.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m I0308 17:16:27.105670 26657 external/com_github_brpc_brpc/src/brpc/server.cpp:1049] Check out http://sgx-stable:49969 in web browser.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m I0308 17:16:27.206267 27076 external/com_github_brpc_brpc/src/brpc/socket.cpp:2202] Checking Socket{id=0 addr=127.0.0.1:33991} (0x55aa8c859e00)\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m I0308 17:16:27.206395 27076 external/com_github_brpc_brpc/src/brpc/socket.cpp:2262] Revived Socket{id=0 addr=127.0.0.1:33991} (0x55aa8c859e00) (Connectable)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PPURuntime pid=26652)\u001b[0m [2022-03-08 17:16:27.179] [info] [context.cc:58] connecting to mesh, id=root, self=1\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m [2022-03-08 17:16:27.105] [info] [context.cc:58] connecting to mesh, id=root, self=0\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m [2022-03-08 17:16:27.124] [info] [context.cc:83] try_connect to rank 1 not succeed, sleep_for 1000ms and retry.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26652)\u001b[0m [2022-03-08 17:16:28.124] [info] [context.cc:111] connected to mesh, id=root, self=1\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m [2022-03-08 17:16:28.124] [info] [context.cc:111] connected to mesh, id=root, self=0\n"
     ]
    }
   ],
   "source": [
    "# 创建一个PPU设备\n",
    "ppu = sf.PPU(sf.utils.testing.cluster_def(['alice', 'bob']))\n",
    "\n",
    "# 使用该PPU创建一个聚合实例。\n",
    "ppu_aggr = sf.security.aggregation.PPUAggregator(ppu)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "ec966557-a996-4a0f-8c65-27989770b849",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 模拟alice、bob分别持有数据\n",
    "a = alice(lambda: arr0)()\n",
    "b = bob(lambda: arr1)()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "cd1ed90a-efed-4022-847b-969a5d7ccb63",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[0.7609336, 1.3277214, 1.0033276],\n",
       "       [1.2734303, 0.4791842, 1.1244376]], dtype=float32)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PPURuntime pid=26652)\u001b[0m 17:16:54 TRACE: [Profiling] PPU execution completed, input processing took 0.000570814s, execution took 7.9804e-05s, output processing took 1.3843e-05s, total time 0.000664461s.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m 17:16:54 TRACE: [Profiling] PPU execution completed, input processing took 0.000588775s, execution took 7.787e-05s, output processing took 1.4256e-05s, total time 0.000680901s.\n"
     ]
    }
   ],
   "source": [
    "# 求和\n",
    "ppu_aggr.sum([a, b], axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "c052616f-f9ca-4ae0-af16-db203110e874",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.38046676, 0.6638607 , 0.5016638 ],\n",
       "       [0.6367152 , 0.23959209, 0.5622188 ]], dtype=float32)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PPURuntime pid=26652)\u001b[0m 17:16:55 TRACE: [Profiling] PPU execution completed, input processing took 0.000130693s, execution took 0.000126421s, output processing took 1.0489e-05s, total time 0.000267603s.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m 17:16:55 TRACE: [Profiling] PPU execution completed, input processing took 0.000125816s, execution took 0.000132241s, output processing took 9.444e-06s, total time 0.000267501s.\n"
     ]
    }
   ],
   "source": [
    "# 求均值\n",
    "ppu_aggr.average([a, b], axis=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bef5c70c-e892-4d2e-806d-d2ec1c37f02c",
   "metadata": {},
   "source": [
    "### Masking with One-Time Pads\n",
    "\n",
    "`Masking with One-Time Pads`的思路为每个参与方和其他参与方协商秘密，然后使用秘密对其输入$x$进行隐藏，每个参与方输出:\n",
    "\n",
    "$$ y_u = x_u + \\sum_{u < v}s_{u,v} - \\sum_{u > v}s_{u,v}\\ mod\\ R  $$\n",
    "\n",
    "，聚合之后秘密被互相抵消从而得到正确的结果:\n",
    "\n",
    "$$ \\sum y = \\sum x $$\n",
    "\n",
    "\n",
    "比如参与方Alice、Bob、Carol各自拥有$x_1,x_2,x_3$，协商出秘密$s_{a,b}, s_{a,c}, s_{b,c}$，然后分别输出:  \n",
    "$y_1 = x_1 + s_{a,b} + s_{a,c}$  \n",
    "$y_2 = x_2 - s_{a,b} + s_{b,c}$  \n",
    "$y_3 = x_3 - s_{a,c} - s_{b,c}$  \n",
    "则容易得到  $$ y_1 + y_2 + y_3 = x_1 + s_{a,b} + s_{a,c} + x_2 - s_{a,b} + s_{b,c} + x_3 - s_{a,c} - s_{b,c} = x_1 + x_2 + x_3 $$\n",
    "\n",
    "注意，`Masking with One-Time Pads`基于半诚实（semi-honest）假设，且不支持掉线。更多内容可以参考[Practical Secure Aggregation\n",
    "for Privacy-Preserving Machine Learning](https://eprint.iacr.org/2017/281.pdf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "874c750c-8c2f-4ba5-a427-eecab2ca6f3c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建一个安全聚合实例: alice、bob作为参与方，其中alice负责执行聚合计算操作。\n",
    "secure_aggr = sf.security.aggregation.SecureAggregator(device=alice, participants=[alice, bob])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f1c6dbb8-b890-4d8f-af97-09068e3bf9ce",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.7609335, 1.3277213, 1.0033275],\n",
       "       [1.2734303, 0.4791841, 1.1244375]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求和\n",
    "secure_aggr.sum([a, b], axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e1907fd5-e26a-4688-b631-cc8ac7b3f838",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.38046675, 0.66386065, 0.50166375],\n",
       "       [0.63671515, 0.23959205, 0.56221875]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求平均\n",
    "secure_aggr.average([a, b], axis=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60410eb4-0137-43cd-86fd-9d4fab394108",
   "metadata": {},
   "source": [
    "### 明文聚合（不推荐在生产场景使用）\n",
    "\n",
    "为了方便本地模拟，隐语还提供了明文聚合器。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "24f57e1d-c6de-48d4-a2ac-5e994b45b62c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建一个明文聚合实例：由alice负责执行聚合。\n",
    "plain_aggr = sf.security.aggregation.PlainAggregator(ppu)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "767c4beb-c416-4a69-ba5a-15ef1ffdd59f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.7609336, 1.3277214, 1.0033276],\n",
       "       [1.2734303, 0.4791842, 1.1244376]], dtype=float32)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PPURuntime pid=26652)\u001b[0m 17:17:05 TRACE: [Profiling] PPU execution completed, input processing took 6.5205e-05s, execution took 4.9977e-05s, output processing took 7.034e-06s, total time 0.000122216s.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m 17:17:05 TRACE: [Profiling] PPU execution completed, input processing took 8.8797e-05s, execution took 4.3523e-05s, output processing took 1.1556e-05s, total time 0.000143876s.\n"
     ]
    }
   ],
   "source": [
    "# 求和\n",
    "plain_aggr.sum([a, b], axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "6046af97-6b2a-4945-b85d-a95bf80a9344",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.38046676, 0.6638607 , 0.5016638 ],\n",
       "       [0.6367152 , 0.23959209, 0.5622188 ]], dtype=float32)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PPURuntime pid=26652)\u001b[0m 17:17:06 TRACE: [Profiling] PPU execution completed, input processing took 0.000131015s, execution took 0.000141545s, output processing took 1.0408e-05s, total time 0.000282968s.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m 17:17:06 TRACE: [Profiling] PPU execution completed, input processing took 0.000161021s, execution took 0.00016127s, output processing took 1.0446e-05s, total time 0.000332737s.\n"
     ]
    }
   ],
   "source": [
    "# 求平均\n",
    "plain_aggr.average([a, b], axis=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ccb4e3cc-b693-432a-b6a6-183d3da40195",
   "metadata": {},
   "source": [
    "## 比较操作。\n",
    "\n",
    "上面我们介绍了```Aggregator```，提供的主要是求和/平均等聚合操作。\n",
    "除此之外，隐语还提供了多种```Comparator```，提供诸如最大(max)/最小(min)操作。\n",
    "比如在数据水平切分场景，可以通过安全比较来得到全局值而不需要暴露参与方的私有信息。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c45ae947-d550-4868-b58a-6d7eafacfc24",
   "metadata": {},
   "source": [
    "### 基于PPU的安全比较\n",
    "\n",
    "隐语实现了基于PPU的安全聚合，下面将展示如何使用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "f3a4ea28-2ac0-468f-addc-527c8b1e3273",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建一个安全聚合实例。\n",
    "ppu_com = sf.security.compare.PPUComparator(ppu)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "59f369d3-75dc-4730-8aed-3efc3d31cedb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.11274984, 0.33600056, 0.43811923],\n",
       "       [0.48992354, 0.22364359, 0.4047367 ]], dtype=float32)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PPURuntime pid=26652)\u001b[0m 17:17:18 TRACE: [Profiling] PPU execution completed, input processing took 6.5205e-05s, execution took 0.001691144s, output processing took 2.2081e-05s, total time 0.00177843s.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m 17:17:18 TRACE: [Profiling] PPU execution completed, input processing took 7.9183e-05s, execution took 0.00170288s, output processing took 2.0364e-05s, total time 0.001802427s.\n"
     ]
    }
   ],
   "source": [
    "# 求最小值\n",
    "sf.reveal(ppu_com.min([a, b], axis=0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "ecb25b3d-c2cc-45a1-863e-d171bc446eb9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.6481837 , 0.99172086, 0.5652083 ],\n",
       "       [0.7835069 , 0.2555406 , 0.7197009 ]], dtype=float32)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PPURuntime pid=26652)\u001b[0m 17:17:19 TRACE: [Profiling] PPU execution completed, input processing took 8.4679e-05s, execution took 0.001681185s, output processing took 7.882e-06s, total time 0.001773746s.\n",
      "\u001b[2m\u001b[36m(PPURuntime pid=26657)\u001b[0m 17:17:19 TRACE: [Profiling] PPU execution completed, input processing took 0.000116569s, execution took 0.001736532s, output processing took 9.873e-06s, total time 0.001862974s.\n"
     ]
    }
   ],
   "source": [
    "# 求最大值\n",
    "ppu_com.max([a, b], axis=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c5090d29-bf15-460a-b941-56bbcffac1f8",
   "metadata": {},
   "source": [
    "### 明文比较（不推荐生产使用）\n",
    "\n",
    "为了方便本地模拟，隐语还提供了明文比较。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "b26ffc58-66a9-4a59-a4c6-5387ed50189d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建一个明文比较对象：由alice负责执行比较。\n",
    "plain_com = sf.security.compare.PlainComparator(alice)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "536bc777-9d5d-442a-ab33-d2215b8bb930",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.11274985, 0.33600056, 0.43811926],\n",
       "       [0.48992354, 0.22364359, 0.40473673]], dtype=float32)"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,840,840 DEBUG [dispatch.py:log_elapsed_time:184] Finished tracing + transforming prim_fun for jit in 0.0005772113800048828 sec\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,840,840 DEBUG [xla_bridge.py:_init_backend:259] Initializing backend 'interpreter'\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,842,842 DEBUG [xla_bridge.py:_init_backend:271] Backend 'interpreter' initialized\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,842,842 DEBUG [xla_bridge.py:_init_backend:259] Initializing backend 'cpu'\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,843,843 DEBUG [xla_bridge.py:_init_backend:271] Backend 'cpu' initialized\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,843,843 DEBUG [xla_bridge.py:_init_backend:259] Initializing backend 'tpu_driver'\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,843,843 INFO [xla_bridge.py:backends:244] Unable to initialize backend 'tpu_driver': NOT_FOUND: Unable to find driver in registry given worker: \n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,843,843 DEBUG [xla_bridge.py:_init_backend:259] Initializing backend 'gpu'\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,843,843 INFO [xla_bridge.py:backends:244] Unable to initialize backend 'gpu': NOT_FOUND: Could not find registered platform with name: \"cuda\". Available platform names are: Interpreter Host\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,844,844 DEBUG [xla_bridge.py:_init_backend:259] Initializing backend 'tpu'\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,844,844 INFO [xla_bridge.py:backends:244] Unable to initialize backend 'tpu': INVALID_ARGUMENT: TpuPlatform is not available.\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,844,844 WARNING [xla_bridge.py:backends:249] No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,845,845 DEBUG [dispatch.py:log_elapsed_time:184] Finished tracing + transforming _reduce_min for jit in 0.0006520748138427734 sec\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,845,845 DEBUG [dispatch.py:lower_xla_callable:229] Compiling _reduce_min (139887474779456 for args (ShapedArray(float32[2,2,3]),).\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:23,858,858 DEBUG [dispatch.py:log_elapsed_time:184] Finished XLA compilation of _reduce_min in 0.010744333267211914 sec\n"
     ]
    }
   ],
   "source": [
    "# 求最小值\n",
    "plain_com.min([a, b], axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "f60702d6-7fa1-49d1-8dc2-08fca911925f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.6481837 , 0.99172086, 0.5652084 ],\n",
       "       [0.7835069 , 0.2555406 , 0.7197009 ]], dtype=float32)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:24,583,583 DEBUG [dispatch.py:log_elapsed_time:184] Finished tracing + transforming _reduce_max for jit in 0.0007154941558837891 sec\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:24,583,583 DEBUG [dispatch.py:lower_xla_callable:229] Compiling _reduce_max (139887474748032 for args (ShapedArray(float32[2,2,3]),).\n",
      "\u001b[2m\u001b[36m(_run pid=26650)\u001b[0m 2022-03-08 17:17:24,593,593 DEBUG [dispatch.py:log_elapsed_time:184] Finished XLA compilation of _reduce_max in 0.008640050888061523 sec\n"
     ]
    }
   ],
   "source": [
    "# 求最大值\n",
    "plain_com.max([a, b], axis=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1bc9bd95-5e58-4361-9c5f-0893edc242cd",
   "metadata": {},
   "source": [
    "## 总结\n",
    "\n",
    "本篇介绍了隐语的安全聚合方案，隐语提供了多种安全聚合方案，用户可以根据自己的需求施行不同的安全策略。\n",
    "对于明文聚合方案，建议在生产环境谨慎使用。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.8.12 ('3.8')",
   "language": "python",
   "name": "python3812jvsc74a57bd0ae1fdd5fd034b7d694352220485921694ff89198520409089b4646721fce11ca"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
